package cn.gs.serializable.old;

// @author gs
import cn.gs.util.stream.TokenReader;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.logging.Level;
import java.util.logging.Logger;

public class SerializableTool {

    public static Object copy(Object o) {
        try {
            Object ins = o.getClass().newInstance();
            BeanInfo infos = Introspector.getBeanInfo(o.getClass(), o.getClass().getSuperclass());
            for (PropertyDescriptor pd : infos.getPropertyDescriptors()) {
                if (pd.getReadMethod() != null && pd.getWriteMethod() != null) {
                    try {
                        pd.getWriteMethod().invoke(ins, pd.getReadMethod().invoke(o));
                    } catch (IllegalArgumentException ex) {
                        Logger.getLogger(SerializableTool.class.getName()).log(Level.SEVERE, null, ex);
                    } catch (InvocationTargetException ex) {
                        Logger.getLogger(SerializableTool.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
            return ins;
        } catch (IntrospectionException ex) {
            Logger.getLogger(SerializableTool.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            Logger.getLogger(SerializableTool.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(SerializableTool.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

    public static <T> T toObject(String s, Class<T> clazz) throws ClassNotFoundException {
        StringReader sr = new StringReader(s);
        TokenReader reader = new TokenReader(sr, "[]{},\":");
        ISerialEntity ise;
        try {
            ise = read(reader);
        } catch (IOException ex) {
            Logger.getLogger(SerializableTool.class.getName()).log(Level.SEVERE, null, ex);
            throw new ClassNotFoundException(s, ex);
        }
        return ise.deserialize(clazz);
    }

    public static String toString(Object o) {
        ISerialEntity e = serialize(o);
        if (e == null) {
            return null;
        }
        StringWriter sw = new StringWriter();
        try {
            e.write(sw);
        } catch (IOException ex) {
            Logger.getLogger(SerializableTool.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
        return sw.toString();
    }

    public static ISerialEntity read(TokenReader reader) throws IOException, ClassNotFoundException {
        ISerialEntity i;
        boolean b;
        i = new SerialArray();
        b = i.read(reader);
        if (b) {
            return i;
        }
        i = new SerialNull();
        b = i.read(reader);
        if (b) {
            return i;
        }
        i = new SerialString();
        b = i.read(reader);
        if (b) {
            return i;
        }
        i = new SerialNumber();
        b = i.read(reader);
        if (b) {
            return i;
        }
        i = new SerialMap();
        b = i.read(reader);
        if (b) {
            return i;
        }
        throw new ClassNotFoundException();
    }

    public static ISerialEntity serialize(Object o) {
        ISerialEntity i;
        boolean b;
        i = new SerialArray();
        b = i.serialize(o);
        if (b) {
            return i;
        }
        i = new SerialNull();
        b = i.serialize(o);
        if (b) {
            return i;
        }
        i = new SerialString();
        b = i.serialize(o);
        if (b) {
            return i;
        }
        i = new SerialNumber();
        b = i.serialize(o);
        if (b) {
            return i;
        }
        i = new SerialMap();
        b = i.serialize(o);
        if (b) {
            return i;
        }
        return null;
    }
}